
public class Rectangle extends Primitive {
	
	private Vector[] p = null;
	private Vector normal = null;
	
	public Rectangle(){
		this.p = new Vector[3];
		for(int i=0; i<3; i++){
			this.p[i] = new Vector();
		}
		this.normal = new Vector(0.0,0.0,0.0);
		this.setSurface(new Surface());
	}
	
	public Rectangle(Vector v0, Vector v1, Vector v2, Surface surface){
		this();
		this.p[0] = v0;
		this.p[1] = v1;
		this.p[2] = v2;
		this.normal = Vector.crossProduct_n(Vector.sub_n(v1, v0), Vector.sub_n(v2, v0));
		this.setSurface(surface);
	}
	
	public Rectangle(Vector v0, Vector v1, Vector v2){
		this();
		this.p[0] = v0;
		this.p[1] = v1;
		this.p[2] = v2;
		this.normal = Vector.crossProduct_n(Vector.sub_n(v1, v0), Vector.sub_n(v2, v0));
	}
	
	public Rectangle(Vector[] args, Surface surface){
		this(args[0], args[1], args[2], surface);
	}
	
	public Vector[] getP(){
		return this.p;
	}
	public void setP(Vector p0, Vector p1, Vector p2) {
		this.p[0]=p0;
		this.p[1]=p1;
		this.p[2]=p2;
		this.updateNormal();
	}
	
	public void setP0(Vector p0) {
		this.p[0]=p0;
		this.updateNormal();
	}
	
	public Vector getP0(){
		return this.p[0];
	}
	
	public void setP1(Vector p1) {
		this.p[1]=p1;
		this.updateNormal();
	}
	
	public Vector getP1(){
		return this.p[1];
	}
	
	public void setP2(Vector p2) {
		this.p[2]=p2;
		this.updateNormal();
	}
	
	public Vector getP2(){
		return this.p[2];
	}
	
	public void updateNormal(){
		this.normal = Vector.crossProduct_n(Vector.sub_n(this.p[1], this.p[0]), Vector.sub_n(this.p[2], this.p[0]));
	}

	public void setNormal(Vector normal) {
		this.normal = normal;
	}
	
	public Vector getNormal(){
		return this.normal;
	}
	
	@Override
	public Vector intersectionPoint_direction(Vector source, Vector direction ){
		if(Vector.dotProduct(direction, this.normal)== 0) { //parallel to plain
			return null; // may want to also check if line is contained in plain
		}
		double Var = (Vector.dotProduct(this.normal, this.p[0]) - Vector.dotProduct(this.normal, source))
					/Vector.dotProduct(this.normal, direction);
		
		if (Var < 0.0) return null;
		
		Vector intersectionPoint = Vector.add(source, direction.mul(Var));		
		Vector otherCorner = Vector.add(this.p[1], Vector.sub(this.p[2], this.p[0]));	
		
		if (Vector.isInAngularRange(this.p[0], this.p[1], this.p[2], intersectionPoint)
				&& Vector.isInAngularRange(otherCorner, this.p[1], this.p[2], intersectionPoint)){
			return intersectionPoint;
		}
		return null;
	}

	@Override
	public Vector getNormalAt(Vector target, Vector viewDirection) {
		Vector outSide = Vector.add(target, viewDirection.mul(-1));
		if (outSide.isUnderPlain(this.p[0], this.normal))return this.normal.mul(-1);
		return this.normal;
	}
	
	
	/*
	@Override
	public Vector getNormalAt(Vector target, Vector viewDirection) {
		if (Vector.cosAngle(normal, viewDirection) <= 0)return normal;
		return normal.mul(-1);
	}
	*/
	
	public static Rectangle getDBGRect(){
		Vector a = new Vector(5,-2.25,5);
		Vector b = new Vector(-5,-2.25,5);
		Vector c = new Vector(5,-2.25,-5);
		Rectangle rec = new Rectangle(a,b,c);
		rec.setMtlDiffuse(new RGB (0.2,0.6,0.5));
		rec.setMtlAmbient(new RGB (0.2,0.6,0.5));
		return rec;
	}

	@Override
	public Vector getLowestPoint() { 
		double[] c0, c1, c2, c3;
		double[] ct = new double[3];
		Vector thirdPoint = Vector.add(p[1], Vector.sub(p[2], p[0]));
		c0 = p[0].getCoords();
		c1 = p[1].getCoords();
		c2 = p[2].getCoords();
		c3 = thirdPoint.getCoords();
		for(int i=0; i<3; i++){
			ct[i] = Math.min(Math.min(c0[i], c1[i]), Math.min(c2[i], c3[i]));
		}
		return new Vector(ct[0], ct[1], ct[2]);
	}

	@Override
	public Vector getHighestPoint() {
		double[] c0, c1, c2, c3;
		double[] ct = new double[3];
		Vector thirdPoint = Vector.add(p[1], Vector.sub(p[2], p[0]));
		c0 = p[0].getCoords();
		c1 = p[1].getCoords();
		c2 = p[2].getCoords();
		c3 = thirdPoint.getCoords();
		for(int i=0; i<3; i++){
			ct[i] = Math.max(Math.max(c0[i], c1[i]), Math.max(c2[i], c3[i]));
		}
		return new Vector(ct[0], ct[1], ct[2]);
	}
}
	

